/**
 * Copyright 2012 Alfredo "Rainbowbreeze" Morresi
 * 
 * This file is part of Eureka! project.
 * 
 * Eureka! is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * Eureka! is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with Eureka!. If not, see http://www.gnu.org/licenses/.
 */
package it.rainbowbreeze.eureka.logic;

import static it.rainbowbreeze.libs.common.RainbowContractHelper.checkNotNull;
import it.rainbowbreeze.eureka.common.LogFacility;
import it.rainbowbreeze.eureka.domain.QualityDataPoint;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import android.text.TextUtils;

/**
 * @author Alfredo "Rainbowbreeze" Morresi
 *
 */
public class JsonConverter {
    // ------------------------------------------ Private Fields
    private static final String LOG_HASH = JsonConverter.class.getSimpleName();
    
    private final LogFacility mLogFacility;
    private static ObjectMapper jsonMapper;

    // -------------------------------------------- Constructors
    public JsonConverter(LogFacility logFacility) {
        mLogFacility = checkNotNull(logFacility, "LogFacility");
        jsonMapper = new ObjectMapper();
    }

    // --------------------------------------- Public Properties
    private boolean mDebug = false;
    public void setDebugMode(boolean newValue) {
        mDebug = newValue;
    }

    // ------------------------------------------ Public Methods
    public String toJson(Object objectToConvert)
    throws IOException, JsonGenerationException, JsonMappingException {
        String result = jsonMapper.writeValueAsString(objectToConvert);
        
        if (mDebug) {
            mLogFacility.v(LOG_HASH, "JSon serialization result: " + result);
        }
        return result;
    }

    /**
     * Converts server return of a quality data point query
     * 
     * @param jsonResponse
     * @param classToConvert
     * @return
     * @throws IOException 
     * @throws JsonMappingException 
     * @throws JsonParseException 
     */
    public QualityDataPoint[] fromServerDataPointsInfo(String jsonResponse)
    throws JsonParseException, JsonMappingException, IOException {
        if (TextUtils.isEmpty(jsonResponse)) return null;
        if ("[]".equals(jsonResponse)) return null;
        
        Object[] rawData = jsonMapper.readValue(jsonResponse, Object[].class);
        
        if (rawData.length == 0) {
            mLogFacility.v(LOG_HASH, "No item returned from server");
            return null;
        }
        QualityDataPoint[] dataPoints = new QualityDataPoint[rawData.length];
        int index = 0;
        for(Object item:rawData) {
            if (item instanceof LinkedHashMap) {
                LinkedHashMap<String, Object> singleObject = (LinkedHashMap<String, Object>) item;
                QualityDataPoint dataPoint = new QualityDataPoint();
                if (singleObject.containsKey("type")) {
                    Integer value = (Integer) singleObject.get("type");
                    dataPoint.setMeasureId(value);
                }
                if (singleObject.containsKey("score")) dataPoint.setScore((Integer) singleObject.get("score"));
                if (singleObject.containsKey("geo")) {
                    ArrayList<Double> coord = (ArrayList<Double>) singleObject.get("geo");
                    Double latitude = (coord.get(0) * 1e6);
                    dataPoint.setLatitude(latitude.intValue());
                    Double longitude = (coord.get(1) * 1e6);
                    dataPoint.setLongitude(longitude.intValue());
                }
                if (singleObject.containsKey("anno")) {
                    LinkedHashMap<String, Object> annoObj = (LinkedHashMap<String, Object>) singleObject.get("anno");
                    if (annoObj.containsKey("sec")) {
                        Integer timestamp = (Integer) annoObj.get("sec");
                        dataPoint.setAcquisitionTimestamp(timestamp);
                    }
                }
                if (singleObject.containsKey("weight")) {
                    double value = (Double) singleObject.get("weight");
                    dataPoint.setWeight(value);
                } else {
                    dataPoint.setWeight(0);
                }
                if (singleObject.containsKey("radius")) {
                    Integer value = (Integer) singleObject.get("radius");
                    dataPoint.setRadius(value * 1000);
                } else {
                    dataPoint.setRadius(5000); //default 5km
                }
                dataPoints[index] = dataPoint;
                index++;
            }
        }
        
        return dataPoints;
    }
    // ----------------------------------------- Private Methods

    public int getWebserviceErrorCode(String messageBody) {
        return 0;
    }

    // ----------------------------------------- Private Classes
}
